// ==UserScript==
// @name         《打工方块人》
// @namespace    https://gitee.com/yiyuzi/youhou/tree/master/
// @version      0.3
// @description  摸鱼鱼鱼
// @author       一语子
// @include      *
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @match        http://*/*
// @icon         
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

'use strict';
console.log("混合方块 start");

// 10*10的棋盘
var chessboardNum;
var chessboard;
// 棋子种类
var chessType;
// 棋子种类数量
var chessTypeNum;
// 备选棋子数量
var chessSelectNum;
// 备选棋子类型
var chessSelectType;
// 备选棋子颜色
var chessSelectColorType;
// 分数
var chessScore;
// 颜色种类
var colorType;
var isHiddenGame;

chessInit();

// 初始化棋盘样式
function chessInit(){
    isHiddenGame = false;
    chessboardNum = 10;
    chessTypeNum = chessSelectNum = chessScore = 0;
    chessboard = new Array(chessboardNum).fill('');
    chessboard = chessboard.map((ele)=>new Array(chessboardNum).fill(false));
    chessType = new Array(15).fill('');
    chessType = chessType.map((ele)=>new Array(4).fill(''));
    chessTypeInit();
    colorType = ["#00BFFF", "#a18cd1", "#ff9a9e", "#d4fc79", "#96e6a1", "#84fab0", "#8fd3f4", "#a1c4fd", "#c2e9fb"];
    if (!GM_getValue("chessScoreMax")) {GM_setValue("chessScoreMax", 0)}

    let _html = `<button id="hiddenGame">隐藏</button><div id="chessGame"><button id="startGame">开始</button><div id="chessScoreMax">最高：${GM_getValue("chessScoreMax")}</div><div id="chessScore">当前：${chessScore}</div><div id='chessboard'>`;
    for (let i = 0; i < chessboardNum; i++){
        for (let j = 0; j < chessboardNum; j++){
            _html += `<div class="chessCell" id="${"chessCell"+i+j}"></div>`;
        }
    }
    _html += `</div><div id="chessWaitSelectBoard">`
    for (let i = 0; i < 3; i++){
        _html += `<div class="chessWaitSelect" id="${"chessWaitSelect"+i}"></div>`;
    }
    _html += `</div></div><style>
    #hiddenGame {
    z-index: 2001;
    position: fixed;
    top: 10%;
    left: 13%;
    }
    #chessGame {
    z-index: 2000;
    position: fixed;
    top: 10%;
    left: 10%;
    background: #fff;
    }
    #chessGame div{
    border-radius: 5px;
    }
    #chessboard {
    display: grid;
    /* 划分行列 */
    grid-template-rows: repeat(10,20px);
    grid-template-columns: repeat(10,20px);
	}
    .chessCell {
    background: #fff;
    box-shadow: 0px 0px 3px 3px rgba(169,169,169, .2);
    height: 15px;
    width: 15px;
    }
    #chessWaitSelectBoard {
    display: grid;
    grid-template-rows: repeat(1,33%);
    grid-template-columns: repeat(4,33%);
    }
    .chessWaitSelect {
    background: #fff;
    box-shadow: 0px 0px 3px 3px rgba(169,169,169, .2);
    height: 60px;
    width: 90%;
    }
    #chessScore {
    background: #fff;
    /*box-shadow: 0px 0px 3px 3px rgba(169,169,169, .2);*/
    height: 40px;
    width: auto;
    }
    </style>`;
    document.body.insertAdjacentHTML('beforeend', _html);
    function bindStartGameBtn(){
        document.getElementById("startGame").addEventListener("click", startGame);
    }
    function bindHiddenGameBtn(){
        document.getElementById("hiddenGame").addEventListener("click", function(){
            if(isHiddenGame){
                $("#hiddenGameStyle").remove();
                isHiddenGame = false;
            }else {
                $("body").append("<style id='hiddenGameStyle'>#chessGame {display:none}</style>");
                isHiddenGame = true;
            }
        });
    }
    setTimeout(bindStartGameBtn, 1000);
    setTimeout(bindHiddenGameBtn, 1000);
}

// 初始化棋子类型
function chessTypeInit() {
	chessType[chessTypeNum++][0] = [[true]];
    chessType[chessTypeNum++][0] = [[true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true, true, true]];
    chessType[chessTypeNum++][0] = [[true, true],
                                    [true, true]];
    chessType[chessTypeNum++][0] = [[true, true],
                                    [true, false]];
    chessType[chessTypeNum++][0] = [[false, true, true],
                                    [true, true, false]];
    chessType[chessTypeNum++][0] = [[true, true, false],
                                    [false, true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [true, false, false]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [false, false, true]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [true, false, true],
                                    [true, false, true]];

	let temp = new Array(5).fill('');
    temp = temp.map((ele)=>new Array(4));
    // chessTypeNum种形状
	for (let shape = 0; shape < chessTypeNum; shape++) {
        // 顺时针旋转
		for (let form = 0; form < 3; form++) {
			// 获取第form种形态，深拷贝数组
			temp = JSON.parse(JSON.stringify(chessType[shape][form]));
            let row = temp.length;
            let col = temp[0].length;
            chessType[shape][form + 1] = new Array(col).fill('');
            chessType[shape][form + 1] = chessType[shape][form + 1].map((ele)=>new Array(row));
			for (let i = 0; i < row; i++) {
				for (let j = 0; j < col; j++) {
					chessType[shape][form + 1][col - 1 - j][i] = temp[i][j];
				}
			}
		}
	}
}

function getRndInteger(min, max) {
    return Math.floor(Math.random() * (max - min) ) + min;
}

function createChess(){
    chessSelectType = [];
    chessSelectColorType = [];
    for (let k = chessSelectNum; k < 3; k++){
        let chess = chessType[getRndInteger(0, chessTypeNum-(chessScore < 200 ? 0 : 1))][getRndInteger(0, 4)];
        let row = chess.length;
        let col = chess[0].length;
        chessSelectType.push(chess);
        chessSelectColorType.push(colorType[getRndInteger(0, colorType.length)]);
        let _html = `<div id="${"chessFall"+k}">`;
        for(let i = 0; i < row; i++){
            for(let j = 0; j < col; j++){
                _html += `<div id="${"chessSelect"+k+i+j}" class="chessSelect" style="${chess[i][j] ? "background: "+chessSelectColorType[k] : "opacity: 0%"};"></div>`;
            }
        }
        _html += `<style id="${"chessFallStyle"+k}">
        #${"chessFall"+k} {
        cursor:pointer;
        display: grid;
        grid-template-rows: repeat(${row},10px);
        grid-template-columns: repeat(${col},10px);
        }
        #${"chessFall"+k} .chessSelect{
        border-radius: 2px;height: 8px;width: 8px;
        }
        </style></div>`;
        document.getElementById("chessWaitSelect"+k).insertAdjacentHTML('beforeend', _html);
        suspensionChess("chessFall"+k);
    }
    chessSelectNum = 3;
}

function suspensionChess(dragId) {
    var startEvt, moveEvt, endEvt;
    // 判断是否支持触摸事件
    if ('ontouchstart' in window) {
        startEvt = 'touchstart';
        moveEvt = 'touchmove';
        endEvt = 'touchend';
    } else {
        startEvt = 'mousedown';
        moveEvt = 'mousemove';
        endEvt = 'mouseup';
    }
    // 获取元素
    var drag = document.getElementById(dragId);
    // 标记是拖曳还是点击
    var isClick = true;
    // 标记位置
    var disX, disY, left, top, starX, starY;
    // 拖动的棋子
    var k = dragId.charAt(dragId.length - 1);
    var chess = chessSelectType[k];
    var row = chess.length;
    var col = chess[0].length;
    // 当前棋盘左上角位置
    var chessGameEle = document.getElementById("chessGame");
    var chessboardEle = document.getElementById("chessboard");
    var chessboardX = chessGameEle.offsetLeft + chessboardEle.offsetLeft;
    var chessboardY = chessGameEle.offsetTop + chessboardEle.offsetTop;

    drag.addEventListener(startEvt, startFun);

    function startFun(e) {
        // 创建临时样式
        let _html = `<style id='tempStyle'>
        #${dragId} {
        position: fixed;
        grid-template-rows: repeat(${row},20px);
        grid-template-columns: repeat(${col},20px);
        }
        #${dragId} .chessSelect{
        border-radius: 5px;height: 15px;width: 15px;
        }
        </style>`;
        document.body.insertAdjacentHTML('beforeend', _html);
        // 阻止页面的滚动，缩放
        e.preventDefault();
        // 兼容IE浏览器
        e = e || window.event;
        isClick = true;
        // 按下时的坐标
        starX = e.touches ? e.touches[0].clientX : e.clientX;
        starY = e.touches ? e.touches[0].clientY : e.clientY;
        // 相对于拖动元素左上角的位置
        disX = starX - drag.offsetLeft;
        disY = starY - drag.offsetTop;
        // 记录原先的位置
        starX = drag.offsetLeft;
        starY = drag.offsetTop;
        // 按下之后监听后续事件
        document.addEventListener(moveEvt, moveFun);
        document.addEventListener(endEvt, endFun);
    }

    function moveFun(e) {
        // 兼容IE浏览器
        e = e || window.event;
        isClick = false;
        left = (e.touches ? e.touches[0].clientX : e.clientX) - disX;
        top = (e.touches ? e.touches[0].clientY : e.clientY) - disY;
        // 限制拖拽的X范围，不能拖出屏幕
        if (left < 0) {
            left = 0;
        } else if (left > document.documentElement.clientWidth - drag.offsetWidth) {
            left = document.documentElement.clientWidth - drag.offsetWidth;
        }
        // 限制拖拽的Y范围，不能拖出屏幕
        if (top < 0) {
            top = 0;
        } else if (top > document.documentElement.clientHeight - drag.offsetHeight) {
            top = document.documentElement.clientHeight - drag.offsetHeight;
        }
        // 触发对应棋盘格子样式变化;
        for (let i = 0; i < chessboardNum; i++){
            for (let j = 0; j < chessboardNum; j++){
                $("#chessCell"+i+j).css("box-shadow", "0px 0px 3px 3px rgba(169,169,169, .2)");
            }
        }
        let y = Math.round((drag.offsetLeft-chessboardX)/20);
        let x = Math.round((drag.offsetTop-chessboardY)/20);
        if (x >= 0 && y >= 0 && x+row <= chessboardNum && y+col <= chessboardNum){
            let chessColorTemp = [];
            let isColor = true;
            for(let i = x; i < x+row && isColor; i++){
                for(let j = y; j < y+col && isColor; j++){
                    if(chess[i-x][j-y]){
                        if(chessboard[i][j]){
                            isColor = false;
                            break;
                        }
                        chessColorTemp.push([i, j]);
                    }
                }
            }
            if (isColor){
                for(let i = 0; i < chessColorTemp.length; i++){
                    $("#chessCell"+chessColorTemp[i][0]+chessColorTemp[i][1]).css("box-shadow", "0px 0px 3px 3px rgba(135,206,250, .8)");
                }
            }
        }
        drag.style.left = left + 'px';
        drag.style.top = top + 'px';
    }

    function endFun(e) {
        document.removeEventListener(moveEvt, moveFun);
        document.removeEventListener(endEvt, endFun);
        // 恢复样式，将方块放置到棋盘上或移回原位
        for (let i = 0; i < chessboardNum; i++){
            for (let j = 0; j < chessboardNum; j++){
                $("#chessCell"+i+j).css("box-shadow", "0px 0px 3px 3px rgba(169,169,169, .2)");
            }
        }
        let y = Math.round((drag.offsetLeft-chessboardX)/20);
        let x = Math.round((drag.offsetTop-chessboardY)/20);
        $("#tempStyle").remove();
        if (x >= 0 && y >= 0 && x+row <= chessboardNum && y+col <= chessboardNum){
            let chessColorTemp = [];
            let isColor = true;
            for(let i = x; i < x+row && isColor; i++){
                for(let j = y; j < y+col && isColor; j++){
                    if(chess[i-x][j-y]){
                        if(chessboard[i][j]){
                            isColor = false;
                            break;
                        }
                        chessColorTemp.push([i, j]);
                    }
                }
            }
            if (isColor){
                for(let i = 0; i < chessColorTemp.length; i++){
                    let tx = chessColorTemp[i][0];
                    let ty = chessColorTemp[i][1];
                    chessboard[tx][ty] = true;
                    $("#chessCell"+tx+ty).css("background", chessSelectColorType[k]);
                }
                // 检查这几行有没有能消除的，更新分数
                for(let i = x; i < x+row; i++){
                    let isClear = true;
                    for(let j = 0; j < chessboardNum; j++){
                        isClear = isClear && chessboard[i][j];
                    }
                    if(isClear) {
                        chessScore += 10;
                        for(let j = 0; j < chessboardNum; j++){
                            $("#chessCell"+i+j).css("background", "#fff");
                            chessboard[i][j] = false;
                        }
                    }
                }
                for(let j = y; j < y+col; j++){
                    let isClear = true;
                    for(let i = 0; i < chessboardNum; i++){
                        isClear = isClear && chessboard[i][j];
                    }
                    if(isClear) {
                        chessScore += 10;
                        for(let i = 0; i < chessboardNum; i++){
                            $("#chessCell"+i+j).css("background", "#fff");
                            chessboard[i][j] = false;
                        }
                    }
                }
                $("#chessScore").text("当前："+chessScore);
                if (chessScore > GM_getValue("chessScoreMax")){
                    GM_setValue("chessScoreMax", chessScore);
                    $("#chessScoreMax").text("最高："+chessScore);
                }
                $("#"+dragId).remove();
                chessSelectNum--;
                if(chessSelectNum == 0){
                    createChess();
                }
                return;
            }
        }
        drag.style.left = starX + 'px';
        drag.style.top = starY + 'px';
    }
}

function startGame(){
    chessSelectNum = chessScore = 0;
    $("#chessFall0").remove();
    $("#chessFall1").remove();
    $("#chessFall2").remove();
    for (let i = 0; i < 10; i++){
        for (let j = 0; j < 10; j++){
           chessboard[i][j] = false;
           $("#chessCell"+i+j).css("background", "#fff");
           $("#chessCell"+i+j).css("box-shadow", "0px 0px 3px 3px rgba(169,169,169, .2)");
        }
    }
    createChess();
}